﻿using DalamudManager.Models;
using DalamudManager.Windows;
using ICSharpCode.SharpZipLib.Zip;
using LibGit2Sharp;
using LibGit2Sharp.Handlers;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;

namespace DalamudManager
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        const string GitDalamud = "https://gitee.com/BAKAOLC/dalamud";

        public Setting Config { get; private set; }

        public static MainWindow Current;

#pragma warning disable IDE0052 // 删除未读的私有成员
        private readonly Mutex LockMutex;
#pragma warning restore IDE0052 // 删除未读的私有成员

        public MainWindow()
        {
            LockMutex = new Mutex(true, "test", out var flag);
            if (!flag)
            {
                MessageBox.Show("不可重复启动");
                Application.Current.Shutdown();
                return;
            }
            InitializeComponent();

            Current = this;
            IsEnabled = false;

            Config = Setting.Load();

            if (!Repository.IsValid(Config.DalamudPath))
            {
                var result = MessageBox.Show("即将从仓库下载框架内容初始化至本地，是否继续？（可能会花费数分钟进行下载）",
                    "未检测到 Dalamud 框架", MessageBoxButton.YesNo);
                switch (result)
                {
                    case MessageBoxResult.Yes:
                    case MessageBoxResult.OK:
                        break;
                    case MessageBoxResult.None:
                    case MessageBoxResult.Cancel:
                    case MessageBoxResult.No:
                        Application.Current.Shutdown();
                        return;
                }
                Visibility = Visibility.Hidden;
                InitDalamud();
            }
            else
                Launch();
        }

        async void InitDalamud()
        {
            ProgressBarWindow init = new("正在初始化框架", "框架下载中……");
            new Thread(() =>
            {
                while (!init.Completed)
                {
                    Thread.Sleep(100);
                }
                Application.Current.Dispatcher.Invoke(() =>
                {
                    init.Close();
                    Launch();
                });
            })
            {
                IsBackground = true
            }.Start();
            init.Show();
            await Task.Run(() => Repository.Clone(GitDalamud + ".git", Config.DalamudPath, new()
            {
                RecurseSubmodules = true,
                OnCheckoutProgress = (_, steps, totals) => init.Update(steps, totals)
            }));
        }

        async void UpdateDalamud()
        {
            Application.Current.Dispatcher.Invoke(() => ButtonUpdateDalamud.IsEnabled = false);
            await Task.Run(() =>
            {
                try
                {
                    using var ReposDalamud = new Repository(Config.DalamudPath);
                    string logMessage = "";
                    var remote = ReposDalamud.Network.Remotes["origin"];
                    var refSpecs = remote.FetchRefSpecs.Select(x => x.Specification);
                    Commands.Fetch(ReposDalamud, remote.Name, refSpecs, null, logMessage);
                }
                catch (Exception e)
                {
                    MessageBox.Show("更新Dalamud时发生异常：\n" + e.Message);
                }
                Application.Current.Dispatcher.Invoke(() => ButtonUpdateDalamud.IsEnabled = true);
            });
        }

        void Launch()
        {
            AutoUpdateChecker.IsChecked = Config.AutoUpdate;

            IsEnabled = true;
            Visibility = Visibility.Visible;

            UpdateDalamudVersionText();

            if (Config.AutoUpdate)
                UpdateDalamud();

            UpdatePluginList();
            UpdateNetworkPluginList();

            new Thread(CheckDalamudInjector) { IsBackground = true }.Start();
        }

        static bool IsProcessStarted(string processName) => Process.GetProcessesByName(processName).Length > 0;
        void CheckDalamudInjector()
        {
            while (true)
            {
                Application.Current.Dispatcher.Invoke(() =>
                InjectorStatusText.Content = !(ButtonLaunchInjector.IsEnabled = !IsProcessStarted("Dalamud_CN")));
                Thread.Sleep(1000);
            }
        }

        void UpdateDalamudVersionText()
        {
            var file = new FileInfo(Path.Combine(Config.DalamudPath, "Dalamud.Injector.exe"));
            if (file.Exists)
            {
                var info = FileVersionInfo.GetVersionInfo(file.FullName);
                Application.Current.Dispatcher.Invoke(() => DalamudVersionText.Content = info.ProductVersion);
            }
            else
                Application.Current.Dispatcher.Invoke(() => DalamudVersionText.Content = "null");
        }

        void UpdatePluginList()
        {
            Application.Current.Dispatcher.Invoke(() =>
            {
                PluginListBox.IsEnabled = false;
                ButtonCurrentPluginStatusChange.IsEnabled = false;
            });
            PluginList.Update(() =>
            {
                Application.Current.Dispatcher.Invoke(() =>
                {
                    var list = PluginList.List?.Select(x => x.Name)?.ToArray();
                    PluginListBox.ItemsSource = list ?? Array.Empty<string>();
                    PluginListBox.IsEnabled = true;
                });
            });
        }

        void UpdateNetworkPluginList()
        {
            Application.Current.Dispatcher.Invoke(() =>
            {
                NetPluginListBox.IsEnabled = false;
                ButtonDownloadCurrentPlugin.IsEnabled = false;
            });
            NetPluginList.Update(() =>
            {
                Application.Current.Dispatcher.Invoke(() =>
                {
                    var list = NetPluginList.List?.Select(x => x.Name)?.ToArray();
                    NetPluginListBox.ItemsSource = list ?? Array.Empty<string>();
                    NetPluginListBox.IsEnabled = true;
                });
            });
        }

        void UpdateDalamud(object sender, RoutedEventArgs e) => UpdateDalamud();

        void LaunchInjector(object sender, RoutedEventArgs e) =>
            Process.Start(Path.Combine(Config.DalamudPath, "Dalamud_CN.exe"));

        void AutoUpdateCheckerChanged(object sender, RoutedEventArgs e)
        {
            if (Config != null)
            {
                Config.AutoUpdate = (bool)AutoUpdateChecker.IsChecked;
                Config.Save();
            }
        }

        void ButtonStartDownload(object sender, RoutedEventArgs e)
        {
            Application.Current.Dispatcher.Invoke(() =>
            {
                PluginInfo info = NetPluginList.List[NetPluginListBox.SelectedIndex];
                if (info != null)
                {
                    ProgressBarWindow init = new("下载中", "Downloading: " + info.InternalName);
                    init.Show();
                    IsEnabled = false;
                    DownloadManager dl = new(info.Path);
                    new Thread(() =>
                    {
                        while (!init.Completed)
                        {
                            init.Update(dl.ReceivedBytes, dl.TotalBytes);
                            Thread.Sleep(100);
                        }
                        Application.Current.Dispatcher.Invoke(init.Close);
                    })
                    {
                        IsBackground = true
                    }.Start();
                    dl.Start((bytes) =>
                    {
                        Application.Current.Dispatcher.Invoke(() =>
                        {
                            var directory = PluginList.GetPluginFolder(info.InternalName);
                            if (_isUpdate)
                            {
                                try
                                {
                                    foreach (var sub in directory.EnumerateDirectories())
                                    {
                                        foreach (var file in sub.EnumerateFiles())
                                            file.Delete();
                                        sub.Delete();
                                    }
                                    directory.Delete();
                                }
                                catch (Exception e)
                                {
                                    MessageBox.Show("插件安装失败:" + Environment.NewLine + e.Message);
                                    Application.Current.Dispatcher.Invoke(() =>
                                    {
                                        IsEnabled = true;
                                    });
                                    UpdatePluginList();
                                    return;
                                }
                            }
                            try
                            {
                                directory.Create();
                                directory = directory.CreateSubdirectory(info.AssemblyVersion);
                            }
                            catch (Exception e)
                            {
                                MessageBox.Show("插件安装失败:" + Environment.NewLine + e.Message);
                                Application.Current.Dispatcher.Invoke(() =>
                                {
                                    IsEnabled = true;
                                });
                                UpdatePluginList();
                                return;
                            }
                            Task.Run(() =>
                            {
                                Zip.UnZipFile(new MemoryStream(bytes), directory.FullName);
                                Application.Current.Dispatcher.Invoke(() =>
                                {
                                    IsEnabled = true;
                                });
                                UpdatePluginList();
                            });
                        });
                    });
                }
            });
        }

        void ButtonChangePluginStatus(object sender, RoutedEventArgs e)
        {
            PluginInfo info = PluginList.List[PluginListBox.SelectedIndex];
            if (info != null)
            {
                if (info.IsDisable)
                    File.Delete(Path.Combine(info.Path, ".disable"));
                else
                    File.WriteAllText(Path.Combine(info.Path, ".disable"), null);
                info.IsDisable = !info.IsDisable;
                Application.Current.Dispatcher.Invoke(() =>
                {
                    ButtonCurrentPluginStatusChange.Content = info.IsDisable ? "启用该插件" : "禁用该插件";
                });
            }
        }

        bool _isUpdate = false;
        void NetPluginListBoxSelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            Application.Current.Dispatcher.Invoke(() =>
            {
                PluginInfo info = NetPluginList.List[NetPluginListBox.SelectedIndex];
                if (info != null)
                {
                    if (PluginList.List.Where(x => x.InternalName == info.InternalName).Any())
                    {
                        _isUpdate = true;
                        ButtonDownloadCurrentPlugin.Content = "替换";
                    }
                    else
                    {
                        _isUpdate = false;
                        ButtonDownloadCurrentPlugin.Content = "下载";
                    }
                    ButtonDownloadCurrentPlugin.IsEnabled = true;
                    CurrentNetworkPluginInfoText.Text = info.ToString();
                }
                else
                {
                    _isUpdate = false;
                    ButtonDownloadCurrentPlugin.Content = "下载";
                    ButtonDownloadCurrentPlugin.IsEnabled = false;
                }
            });
        }

        void PluginListBoxSelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            Application.Current.Dispatcher.Invoke(() =>
            {
                PluginInfo info = PluginList.List[PluginListBox.SelectedIndex];
                if (info != null)
                {
                    CurrentPluginInfoText.Text = info.ToString();
                    ButtonCurrentPluginStatusChange.IsEnabled = true;
                    ButtonCurrentPluginStatusChange.Content = info.IsDisable ? "启用该插件" : "禁用该插件";
                }
                else
                    ButtonCurrentPluginStatusChange.IsEnabled = false;
            });
        }

        void ButtonRefreshPluginList(object sender, RoutedEventArgs e) => UpdatePluginList();

        void ButtonRefreshNetworkPluginList(object sender, RoutedEventArgs e) => UpdateNetworkPluginList();

        private void Window_Closed(object sender, EventArgs e)
            => Application.Current.Shutdown();
    }
}
